/**
 * 
 */
package mblog.core.persist.dao.impl;

import java.util.Collection;
import java.util.List;

import mblog.core.persist.dao.PostDao;
import mtons.modules.persist.impl.DaoImpl;
import mtons.modules.pojos.Page;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import com.faxsun.core.persist.entity.PostPO;
import com.faxsun.core.pojos.enums.PostType;

/**
 * @author langhsu
 *
 */
public class PostDaoImpl extends DaoImpl<PostPO> implements PostDao {
	private static final long serialVersionUID = -8144066308316359853L;

	public PostDaoImpl() {
		super(PostPO.class);
	}

	@Override
	public Session getSession() {
		return super.session();
	}

	@Override
	public List<PostPO> paging(Page page, PostType type) {
		// FIXME: use constants instead of magic number
		return this.pageingByStatus(page, type, 1);
	}

	@Override
	public List<PostPO> pagingByUserId(Page page, long userId) {
		return this.pagingByUserId(page, userId, 1);
	}

	@Override
	public List<PostPO> pagingByUserId(Page page, long userId, int status) {
		PagingQuery<PostPO> q = pagingQuery(page);
		if (userId > 0) {
			q.add(Restrictions.eq("author.id", userId));
		}
		if (status >= 0)
			q.add(Restrictions.eq("status", status));// 文章状态
		q.desc("created");
		return q.list();
	}

	@Override
	public List<PostPO> findRecents(int maxResutls, long ignoreUserId) {
		TopQuery<PostPO> q = topQuery(maxResutls);
		q.add(Restrictions.neOrIsNotNull("title", ""));
		if (ignoreUserId > 0) {
			q.add(Restrictions.ne("author.id", ignoreUserId));
		}
		q.add(Restrictions.eq("status", 1));// 状态为已发布
		q.desc("created");
		return q.list();
	}

	@Override
	public List<PostPO> findRecents(int maxResutls, long ignoreUserId,
			int postType) {
		TopQuery<PostPO> q = topQuery(maxResutls);
		q.add(Restrictions.neOrIsNotNull("title", ""));
		q.add(Restrictions.eq("type", postType));
		if (ignoreUserId > 0) {
			q.add(Restrictions.ne("author.id", ignoreUserId));
		}
		q.add(Restrictions.eq("status", 1));// 状态为已发布
		q.desc("created");
		return q.list();
	}

	@Override
	public List<PostPO> findHots(int maxResutls, long ignoreUserId) {
		TopQuery<PostPO> q = topQuery(maxResutls);
		q.add(Restrictions.neOrIsNotNull("title", ""));
		// if (ignoreUserId > 0) {
		// q.add(Restrictions.ne("author.id", ignoreUserId));
		// }
		q.desc("views");
		q.add(Restrictions.eq("status", 1));
		return q.list();
	}

	@Override
	public List<PostPO> findByIds(Collection<Long> ids) {
		return find(Restrictions.in("id", ids));
	}

	@Override
	public List<PostPO> findByTags(Page page, List<String> tags, PostType type) {
		// FIXME:未考虑文章删除的情况
		int pageCountTotal = countPageTotalForTag(tags, type);
		return findByTagsForPage(page, tags, type, pageCountTotal);
	}

	@Override
	public List<PostPO> findHots(int maxResutls, PostType type) {
		TopQuery<PostPO> q = topQuery(maxResutls);
		q.add(Restrictions.neOrIsNotNull("title", ""));
		// if (ignoreUserId > 0) {
		// q.add(Restrictions.ne("author.id", ignoreUserId));
		// }
		q.add(Restrictions.eq("type", type.getValue()));
		q.add(Restrictions.eq("status", 1));// 状态为已发布
		q.desc("views");
		return q.list();
	}

	@Override
	public List<PostPO> findRecentByTags(int maxResutls, long ignoreUserId,
			int postType, List<String> tags) {
		// FIXME not using ignoreUserId
		return findByTags(new Page(maxResutls), tags, PostType.parse(postType));
	}

	@Override
	public int countRecentByTags(long ignoreUserId, int postType,
			List<String> tags) {
		// FIXME not using ignoreUserId
		return countPageTotalForTag(tags, PostType.parse(postType));
	}

	private int countPageTotalForTag(List<String> tags, PostType type) {
		// FIXME:仅列出已发布文章
		String hqlCount = "select count(p.id) from PostPO p "
				+ "join p.tagSets t "
				+ "where t.name in (:tags) and p.type=:type "
				+ "and p.status=1 " + "group by p "
				+ "having count(t)=:tag_count ";

		Query countQuery = this.createQuery(hqlCount);
		countQuery.setParameterList("tags", tags);
		countQuery.setInteger("tag_count", tags.size());
		countQuery.setInteger("type", type.getValue());
		@SuppressWarnings("unchecked")
		List<Number> result = countQuery.list();
		return result.size();
	}

	@SuppressWarnings("unchecked")
	public List<PostPO> findByTagsForPage(Page page, List<String> tags,
			PostType type, int pageTotalCount) {
		// FIXME:仅列出已发布文章
		String hql = "select p from PostPO p " + "join p.tagSets t "
				+ "where t.name in (:tags) and p.type=:type "
				+ "and p.status=1 " + "group by p "
				+ "having count(t)=:tag_count "
				+ "order by p.featured,p.created desc";
		page.setTotalCount(pageTotalCount);

		Query query = this.createQuery(hql);
		query.setParameterList("tags", tags);
		query.setInteger("tag_count", tags.size());
		query.setInteger("type", type.getValue());
		query.setFirstResult(page.getFirstResult());
		if (page.getMaxResults() > 0)
			query.setMaxResults(page.getMaxResults());
		return query.list();
	}

	/**
	 * 按状态查找,status=0,待审核；status＝1，已发布；status＝2，删除
	 */
	@Override
	public List<PostPO> pageingByStatus(Page page, PostType type, int status) {
		PagingQuery<PostPO> q = pagingQuery(page);
		q.desc("created");
		if (type == PostType.INVALID) {
			type = null;
		}
		if (type != null) {
			q.add(Restrictions.eq("type", type.getValue()));
		}
		if (status >= 0)
			q.add(Restrictions.eq("status", status));// 状态为已发布

		return q.list();
	}

}
